:- module(dbserver, 
	[get_relationsdb/2,
	 consultdb/3,
         dying/1,
	 die/1,
	 status/1,
         updatetemplates/2,
         consultdboptions/3,
	 create_destroy_table/3,
	 select_table_to_edit/2,
	 edit_table/3],
	 [assertions, runtime_ops, pillow, persdb, persdb_sql]).

%%%%%% A server (an active module) to manage persistent databases %%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%% Needed modules %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- use_module(engine(internals), [initialization/1]).
:- use_module(library(file_utils), [file_to_string/2]).
:- use_module(library(lists)).
:- use_module(library(system)).
:- use_module(library(aggregates)).
:- use_module(library(dynamic)).
:- use_module(library(streams)).
:- use_module(library(read)).
:- use_module(library(write)).
:- use_module(library(metaterms), [atom_concat/2]).
:- use_module(library(patterns)).
%:- use_module(library(messages)).
 
%%%%%%%%%%%% Database description  and html format predicates %%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- include(password).                         % defines fact password/1

:- data html_format/3.                        % defines fact html_format/3
:- data type_val_info/4.                      % defines fact type_val_info/4
:- data type_info/3.                          % defines fact type_info/3
:- data sql_persistent_location/2.            % defines fact sql_persistent_location/2
:- data html2sql/2.                           % defines fact html2sql/2
:- data option_table_size/2.                  % defines fact option_table_size/2

:- persistent(text_option/3, db_description).
:- persistent(search/3, db_description). 
:- persistent(dbtables_desc/2, db_description).

:- data dbtable/5. % ID, Description, Arity, FieldTypes, Site

:- data html_option/4. % Name, Explanation, Params, HTML_code

:- data db_dir/1, db_url/1, db_types/1. % End in '/' !

:- comment(title,"dbserver Documentation").
:- comment(module, "This file is part of the @apl{WebDB} documentation and is aimed
to describe its database server, @concept{dbserver}, which provides the users with 
@concept{services} to access a given database. This server has been developed as a 
@apl{CIAO prolog} @concept{active module} and is basically an executable which publishes 
its IP address in order to allow client programs to use its services. 
").
:- comment(usage,"This module is typically accessed by importing the file
   @tt{dbserver.pl} according to the active modules syntax:
@begin{verbatim}
:- use_active_module(dbserver).
@end{verbatim}
").

:- pred get_relationsdb(ClientType, Response) : passwd * output_page
        ; "Displays an HTML form with a menu where the user can choose the table
to operate on. It makes out wether the user is an authorised client or not by 
checking the argument @var{ClientType}. If it's an authorised client, the user will 
be allowed to insert, delete or modify data, otherwise just consult the system to make
standard search operations".

:- pred consultdb(Input, ClientType, Response) : Input * passwd * output_page
	; "Once the user has decided on which table to operate on through the service 
provided by @pred{get_relationsdb}, @pred{consultdb} displays the system consult 
interface. Through this interface the user can choose which operation to carry out. 
Initially, if the user is an authorised client, these operations can be:
@begin{itemize}
@item @em{Search}: Sequential search. The results of the query are displayed one by one 
	as the user requests them.
@item @em{Overview}: All the tuples that instantiate the query are displayed in a table, 
	but just as prolog facts, without the additional information supplied by the
        the HTML types of its fields.
@item @em{Full search}: As in the case of the @em{Overview} operation, all the tuples
	that instantiate the query are displayed with the additional information 
        of its field types but, in this case, the user can edit the results too.
@item @em{Insert element}: Allows the user to insert a new element, which has to be 
	ground,	e.g. no field of the form can remain empty. Besides, the system tests 
        that the element to be inserted doesn't exist in the table already.
@item @em{Delete element}: Deletes all the tuples that instantiate the query.
@end{itemize}
If the user is not an authorised client, the operations allowed will only be @em{Search},
@em{Overview} and @em{Full search} which, in this case, will not allow the user to edit 
the results of a previous query. 

Note that when any query is made over a database table, the information written 
into the form fields is taken as prolog terms. This way, any empty field of 
the form is translated into a free variable and therefore will unify all the 
corresponding arguments of the given table. 

Besides, @apl{WebDB} provides the user with three different search modes:
@begin{itemize}
@item @em{Case insensitive search mode}: Enhances an upper and lower case insensitive 
	search.
@item @em{Wildcards search mode}: Enhances a search where regular expressions and 
	wildcards (*, ?) can be used. It is quite useful to make finer grain searches, 
	concerning the arguments of the tuples. 
@item @em{Normal search mode}:  The results of the query will be just those tuples that 
	unify with it. Obviously, it is the most restrictive search mode.
@end{itemize}".

:- pred updatetemplates(ClientType, Response) : passwd * output_page
	; "This service is used to reload the HTML templates, which set down the settings,
or any of the files that define the types used, after having edited any of them. This 
way, the system administrator can customize the system on the line, with no need to stop 
it. 
Only authorised clients can use this service.".
	
:- pred consultdboptions(Input, ClientType, Response): dic * passwd * output_page
	; "Service which provides an interface to edit on line every system message and, 
in general, text, for example, the text of any link, the heading or title of any page or 
the message given when an element has been successfully inserted. 
Only authorised clients can use this service.".          

:- pred create_destroy_table(Input, ClientType, Response) : dic * passwd, output_page
	; "Provides an interface where the user can create a new table or destroy an
already existing one, or both at the same time. Tables created this way have arity zero 
and need to be subsequently edited afterwards through the service @pred{edit_table}.
Only authorised clients can use this service.".

:- pred select_table_to_edit(Passwd, Response) : passwd * output_page
	;"Quite similar to @pred{get_relationsdb}, provides a menu to choose the table 
whose field types the user wants to edit.
Only authorised members can use this service.".

:- pred edit_table(Input, Passwd, Response) : dic * passwd * output_page
	;"Once the user has selected through @pred{select_table_to_edit} the table to 
be edited, provides an interface which ehances the user to edit any type of its fields or
add a new one with a given type.
Only authorised members can use this service.".

:- pred  status(Response) : ouput_page
	; "Returns information about the system status.".

:- pred die(ClientType): passwd ; 
"Once the database has been updated in order to keep all the information in a consistant 
state, it halts the database server.
Only authorised members can use this service.".

:- pred dying(ClientType, Response) : passwd * output_page
	;"Before having halted the database server through @pred{die}, it is used to 
produce a message, pointing out that the system is about being halted.
Only authorised members can use this service.".

